package com.boss.salary.service.impl;

import com.boss.common.entity.PageDTO;
import com.boss.common.entity.WfActionDTO;
import com.boss.common.enums.ActionTypeEnum;
import com.boss.common.service.ICommonService;
import com.boss.common.util.DateUtils;
import com.boss.framework.dto.PaginationDTO;
import com.boss.framework.exception.AppRuntimeException;
import com.boss.salary.constant.SystemDictConstant;
import com.boss.salary.dao.*;
import com.boss.salary.entity.AgencyVerify;
import com.boss.salary.entity.SalaryRental;
import com.boss.salary.service.IAgencyVerifyService;
import com.boss.salary.vo.unitReportVO;
import com.boss.salary.workflow.service.ISalaryWorkFlowService;
import com.boss.sys.ca.user.dto.UserDTO;
import com.boss.sys.utils.SysUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AgencyVerifyServiceImpl implements IAgencyVerifyService {

    /**
     * 引入日志框架常量
     */
    private final static Logger logger = LoggerFactory.getLogger(AgencySalaryServiceImpl.class);
    private static DateFormat df = new SimpleDateFormat("yyyy-MM");

    @Autowired
    private IAgencyVerifyDao iAgencyVerifyDao;
    @Autowired
    private IAgencyInfoDao iAgencyInfoDao;
    @Autowired
    private IPersonExtDao iPersonExtDao;
    @Autowired
    private IPersonOperateDao iPersonOperateDao;
    @Autowired
    private IPersonExtSubmitDao iPersonExtSubmitDao;
    @Autowired
    private IPersonExtBeginDao iPersonExtBeginDao;
    @Autowired
    private ISalaryWorkFlowService iSalaryWorkFlowService;
    @Autowired
    private ISalaryMonthEndSubmitDao salaryMonthEndSubmitDao;
    @Autowired
    private IPayMentLockDao iPayMentLockDao;
    @Autowired
    private ICommonService commonService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAgencyVerify(AgencyVerify agencyVerify) {
        agencyVerify.setCreateTime(String.valueOf(DateUtils.getCurrentTimeStamp()));
        agencyVerify.setUpdateTime(String.valueOf(DateUtils.getCurrentTimeStamp()));
        agencyVerify.setIsDeleted(SystemDictConstant.IS_FALSE);
        iAgencyVerifyDao.saveAgencyVerify(agencyVerify);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAgencyVerify(UserDTO userDTO, AgencyVerify agencyVerify) throws AppRuntimeException {
        agencyVerify.setUpdateTime(String.valueOf(DateUtils.getCurrentTimeStamp()));
        iAgencyVerifyDao.updateAgencyVerify(agencyVerify);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)//@GlobalTransactional(timeoutMills=300000)
    public void reportUnitSalary(UserDTO userDTO, AgencyVerify agencyVerify, String tokenid) throws AppRuntimeException {
        AgencyVerify agencyVerify1 = iAgencyVerifyDao.getInfoByAgencyId(agencyVerify.getAgencyId());
        // 上报
        agencyVerify.setIsSalarySubmit(SystemDictConstant.IS_TRUE);
        agencyVerify.setUpdateTime(String.valueOf(DateUtils.getCurrentTimeStamp()));
        iAgencyVerifyDao.updateAgencyVerify(agencyVerify);
        logger.info("=== 修改单位审核表状态后，录入工作流信息Begin ===");
        // 获取单位审核状态信息
        // 单位上报录入流程
        WfActionDTO<AgencyVerify> wfActionDTO = new WfActionDTO();
        wfActionDTO.setMenuguid(agencyVerify.getMenuid());
        // 如果是撤销的，再次上报为审核
        wfActionDTO.setActionType(ActionTypeEnum.WF_AUDIT.getActionTypeCode());
        wfActionDTO.setBizDatas(agencyVerify1);
        wfActionDTO.setBizKeyName("bizKey");
        iSalaryWorkFlowService.doSalaryFlow(userDTO, wfActionDTO, tokenid);
        logger.info("==== 工作流录入完毕End  ===");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)//@GlobalTransactional(timeoutMills=300000)
    public void reportRevokeUnitSalary(UserDTO userDTO, AgencyVerify agencyVerify, String tokenid) throws AppRuntimeException {
        agencyVerify.setIsSalarySubmit(Integer.parseInt(SystemDictConstant.REVOKE));
        agencyVerify.setUpdateTime(String.valueOf(DateUtils.getCurrentTimeStamp()));
        iAgencyVerifyDao.updateAgencyVerify(agencyVerify);
        logger.info("=== 修改单位审核表状态后，撤销工作流信息Begin ===");
        // 获取单位审核状态信息
        AgencyVerify agencyVerify1 = iAgencyVerifyDao.getInfoByAgencyId(agencyVerify.getAgencyId());
        // 单位撤销上报
        WfActionDTO<AgencyVerify> wfActionDTO = new WfActionDTO();
        wfActionDTO.setMenuguid(agencyVerify.getMenuid());
        // 撤销上报
        wfActionDTO.setActionType(ActionTypeEnum.WF_RECALL.getActionTypeCode());
        wfActionDTO.setBizDatas(agencyVerify1);
        wfActionDTO.setBizKeyName("bizKey");
        iSalaryWorkFlowService.doSalaryFlow(userDTO, wfActionDTO,tokenid);
        logger.info("==== 工作流撤销审核完毕End  ===");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)//@GlobalTransactional(timeoutMills=300000)
    public void reportUnitSalaryBack(AgencyVerify agencyVerify, UserDTO userDto,String tokenid) {
        // 获取单位审核状态信息
        AgencyVerify agencyVerify1 = iAgencyVerifyDao.getInfoByAgencyId(agencyVerify.getAgencyId());
        logger.info("====单位上报退回工作流 Begin ====");
        WfActionDTO<AgencyVerify> wfActionDTO = new WfActionDTO();
        wfActionDTO.setMenuguid(agencyVerify.getMenuid());
        wfActionDTO.setActionType(ActionTypeEnum.WF_BACK.getActionTypeCode());
        wfActionDTO.setBizDatas(agencyVerify1);
        wfActionDTO.setBizKeyName("bizKey");
        wfActionDTO.setMessage(agencyVerify.getAuditExplain());


        iSalaryWorkFlowService.doSalaryFlow(userDto, wfActionDTO,tokenid);
        logger.info("==== 单位上报退回工作流 End  ===");
        agencyVerify.setIsSubmitInAgency(Integer.parseInt(SystemDictConstant.IS_REJECT));
        agencyVerify.setSalaryVerifiedInAgencyCode(SystemDictConstant.IS_REJECT);
        agencyVerify.setUpdateTime(String.valueOf(DateUtils.getCurrentTimeStamp()));
        iAgencyVerifyDao.updateAgencyVerify(agencyVerify);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)//@GlobalTransactional(timeoutMills=300000)
    public void updateSalaryVerify(UserDTO userDTO, SalaryRental salaryRental,String tokenid) throws AppRuntimeException {
        List<AgencyVerify> agencyVerify1s = iAgencyVerifyDao.getAgencyVerifyByAgencyIds(salaryRental.getAgencyIds());
        // 单位上报录入流程
        WfActionDTO<List<AgencyVerify>> wfActionDTO = new WfActionDTO();
        wfActionDTO.setMenuguid(salaryRental.getMenuid());
        // 审核
        wfActionDTO.setActionType(ActionTypeEnum.WF_AUDIT.getActionTypeCode());
        wfActionDTO.setBizDatas(agencyVerify1s);
        wfActionDTO.setBizKeyName("bizKey");
//            wfActionDTO.setMessage("财政确认");
        // 财政确认后，执行工作流节点到下一节点
        logger.info("==== 批量工作流财政确认Start  ===");
        iSalaryWorkFlowService.doSalaryFlowList(userDTO, wfActionDTO,tokenid);
        logger.info("==== 批量工作流财政确认完毕End  ===");

    }

    @Override
    @Transactional(rollbackFor = Exception.class)//@GlobalTransactional(timeoutMills=300000)
    public void sendBackSalaryVerify(UserDTO userDto, SalaryRental salaryRental,String tokenid) throws AppRuntimeException {
        // 财政撤销，执行工作流
        for (String agencyId : salaryRental.getAgencyIds()) {
            if(StringUtils.isEmpty(agencyId)){
                continue;
            }
            // 获取单位审核状态信息
            AgencyVerify agencyVerify1 = iAgencyVerifyDao.getInfoByAgencyId(agencyId);
            // 单位上报录入流程
            WfActionDTO<AgencyVerify> wfActionDTO = new WfActionDTO();
            wfActionDTO.setMenuguid(salaryRental.getMenuid());
            // 撤销
            wfActionDTO.setActionType(ActionTypeEnum.WF_RECALL.getActionTypeCode());
            wfActionDTO.setBizDatas(agencyVerify1);
            wfActionDTO.setBizKeyName("bizKey");
            wfActionDTO.setMessage("");
            iSalaryWorkFlowService.doSalaryFlow(userDto, wfActionDTO,tokenid);
            logger.info("==== 工作流财政撤销完毕End  ===");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateChangePersonNum(String agencyId) {
        iAgencyVerifyDao.updateChangePersonNum(agencyId);
    }

    @Override
    public void updateAddPersonNum(String agencyId) {
        iAgencyVerifyDao.updateAddPersonNum(agencyId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAddQuitPersonNum(String agencyId) {
        iAgencyVerifyDao.updateAddQuitPersonNum(agencyId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDeletePersonNum(String agencyId) {
        iAgencyVerifyDao.updateDeletePersonNum(agencyId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)//@GlobalTransactional(timeoutMills=300000)
    public void sendBackSalaryVerify1(UserDTO userDto, SalaryRental salaryRental,String tokenid) throws AppRuntimeException, JsonProcessingException {
        List<Object[]> params =new ArrayList<>();
        String year=iAgencyVerifyDao.currentYear(salaryRental.getAgencyIds());
        // 如果参数中包含退回到单位上报标识，修改状态
        List<AgencyVerify> agencyVerify1s= iAgencyVerifyDao.getSalaryDataByAgencyId(salaryRental.getAgencyIds());
        if(StringUtils.isEmpty(agencyVerify1s)){
            return;
        }
        // 财政退回，执行工作流
        for (AgencyVerify agencyVerify1: agencyVerify1s) {

            // 获取单位审核状态信息
            Object[] updateObjects = new Object[] {
                    //若是自动上报，则在退回的时候将单位是否上报字段修改未未上报，直接退回到编报岗
                    SystemDictConstant.IS_SUBMIT.equals(agencyVerify1.getIsAuto())||"220723990".equals(userDto.getProvince())||salaryRental.getParams().contains(SystemDictConstant.WORK_FLOW_REPORT_START)?SystemDictConstant.IS_REJECT:agencyVerify1.getIsSubmitInAgency(),
                    SystemDictConstant.IS_REJECT, SystemDictConstant.IS_FALSE, agencyVerify1.getAgencyId(), SystemDictConstant.IS_FALSE,
            };
            params.add(updateObjects);

        }

        // 单位上报录入流程
        WfActionDTO<List<AgencyVerify> > wfActionDTO = new WfActionDTO();
        wfActionDTO.setMenuguid(salaryRental.getMenuid());
        // 退回
        wfActionDTO.setActionType(ActionTypeEnum.WF_BACK.getActionTypeCode());

        wfActionDTO.setBizDatas(agencyVerify1s);
        wfActionDTO.setBizKeyName("bizKey");
        wfActionDTO.setMessage(salaryRental.getAuditExplain());
//            wfActionDTO.setMessage("财政确认");
        logger.info("==== 工作流财政退回完毕Start  ===");
        iSalaryWorkFlowService.doSalaryFlowList(userDto, wfActionDTO,tokenid);
        logger.info("==== 工作流财政退回完毕End  ===");
        // 如果参数中包含退回到单位上报标识，修改状态
        if (!StringUtils.isEmpty(salaryRental.getParams()) &&
                salaryRental.getParams().contains(SystemDictConstant.WORK_FLOW_REPORT)) {
            //若为带退回到单位标识则，删除上报数据
            iPersonExtSubmitDao.batchPhysicalDeletePersonExtSubmit(userDto.getProvince(), salaryRental.getAgencyIds());
            salaryMonthEndSubmitDao.batchPhysicalDeleteSalaryMonthSubmit(userDto.getProvince(), salaryRental.getAgencyIds());
            iAgencyVerifyDao.updateSalaryVerify(params);
            //获取已锁定指标
            List<Map<String,Object>> payLockMap=iPayMentLockDao.selectPayMentLock(salaryRental.getAgencyIds());
            //解冻指标
            if(!CollectionUtils.isEmpty(payLockMap)) {
                commonService.batchGocpurbudgetThaw(payLockMap, userDto.getProvince(), year, tokenid,userDto);
                //清楚指标锁定表该单位的锁定信息
                iPayMentLockDao.batchPhysicalDeletePayMentLock(salaryRental.getAgencyIds());
            }

        }
    }

    @Override
    public int getAddPersonNumByAgencyId(String agencyId) {
        return iAgencyVerifyDao.getAddPersonNumByAgencyId(agencyId);
    }

    @Override
    public List<String> getHistoryMonthList(String agencyId) {
        Map<String, Object> map = iAgencyVerifyDao.selectStateByAgencyId(agencyId, "salary_month");
        if(CollectionUtils.isEmpty(map) || StringUtils.isEmpty(map.get("salary_month"))){
            return Collections.emptyList();
        }
        List<String> historyMonthList = new ArrayList<>();
        String salaryMonth = String.valueOf(map.get("salary_month"));
        for(int i = 1; i < 13; i++){
            String historyMonth = LocalDate.parse(salaryMonth+"-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"))
                    .minusMonths(i).format(DateTimeFormatter.ofPattern("yyyy-MM"));
            historyMonthList.add(historyMonth);
        }
        return historyMonthList;
    }

    @Override
    public List<AgencyVerify> getAgencyVerifyInfo() {
        return iAgencyVerifyDao.getAgencyVerifyInfo();
    }

    @Override
    public PageDTO<unitReportVO> getUnitReportPage(PaginationDTO paginationDTO, String state, List<String> childrenId, String mofDivCode,String is_auto) {
        List<unitReportVO> unitReportVOS = iAgencyVerifyDao.selectUnitReportPage(paginationDTO, state, childrenId, mofDivCode,is_auto);
        int total = iAgencyVerifyDao.selectUnitReportTotal(state, childrenId, mofDivCode,is_auto);
        PageDTO<unitReportVO> PageDTO = new PageDTO<>();
        PageDTO.setRows(unitReportVOS);
        PageDTO.setTotal(total);
        return PageDTO;
    }

    @Override
    public AgencyVerify getAgencyVerifyByAgencyId(String agencyId) {
        return iAgencyVerifyDao.getAgencyVerifyByAgencyId(agencyId);
    }

    @Override
    public boolean getSalaryDataByAgencyId(List<String> agencyIds) {
        List<AgencyVerify> list = iAgencyVerifyDao.getSalaryDataByAgencyId(agencyIds);
        Set<Integer> set = list.stream().map(AgencyVerify::getIsPayDataCreated).collect(Collectors.toSet());
        // 生成状态，false：未生成 true：已生成
        boolean result = false;
        // 如果有单位已生成工资数据，则返回false
        for (Integer i : set) {
            if (i == 1) {
                result = true;
                break;
            }
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> selectOverlapPersionInfo(UserDTO userDto, List<String> agencyIds) {
        List<Map<String,Object>> personIds=iAgencyVerifyDao.selectOverlapPersionIds(userDto.getProvince());
        if(!CollectionUtils.isEmpty(personIds)){
            return iAgencyVerifyDao.selectOverlapPersionInfo(userDto.getProvince());
        }else {
            return null;
        }
    }

    @Override
    public boolean checkAgencyIsChanged(String agencyId)  throws Exception{
        Map<String, Object> map=iAgencyVerifyDao.checkAgencyIsChanged(agencyId);
        Map<String,Object> queryParam=new HashMap<>();
        queryParam.put("agencyId",agencyId);
        int total = iPersonOperateDao.getPersonChangeTotal(queryParam);
        if(CollectionUtils.isEmpty(map)){
            throw new Exception("获取变动情况异常");
        }

        String joinconut=map.get("joinconut").toString();
        String nowcount=map.get("nowcount").toString();
        if(StringUtils.isEmpty(joinconut)||StringUtils.isEmpty(nowcount)) {
            throw new Exception("获取变动情况异常");
        }
        //全匹配说明没有变化s
        boolean flag=joinconut.equals(nowcount)&&total==0;
        //返回是否变化
        return !flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<AgencyVerify> insertAgencyLnIt(UserDTO userDTO, List<AgencyVerify> agencyVerifyList) {
        //将前台的传过来的agencyVerifyList 去agencyInfo表中查相同的数据
         List<AgencyVerify> agencyInfoList=iAgencyVerifyDao.queryAgencyIfo(agencyVerifyList,userDTO);
         List<AgencyVerify> addList = new ArrayList<>();
         List<AgencyVerify> updateList = new ArrayList<>();
         List<AgencyVerify> agencyVerifyAdd= new ArrayList<>();
        if (agencyInfoList != null && agencyInfoList.size() > 0) {

            //将重复数据循环
            for(AgencyVerify a:agencyInfoList) {
                for (int i = 0; i < agencyVerifyList.size(); i++) {
                    // 将前台传过来得数据 和 查出来得数据比对
                    if (a.getAgencyId().equals(agencyVerifyList.get(i).getAgencyId())) {
                        //判断平台agencycode是否有改动，如果有改动存入updateList中并将其修改
                      //  if (!a.getAgencyCode().equals(agencyVerifyList.get(i).getAgencyCode())) {
                            updateList.add(agencyVerifyList.get(i));
                      //  }
                        // 如果 有相同的 则干掉
                        agencyVerifyList.remove(i);
                        i--;
                    }
                }
            }
        }

        // 循环对象 并 存入agencyInfoList里
            for(AgencyVerify agencyVerify:agencyVerifyList){
            String year= agencyVerify.getSalaryMonth().substring(0,4);
            agencyVerify.setId(SysUtils.generateGuid());
            agencyVerify.setBizKey(SysUtils.generateGuid());
            agencyVerify.setCreateTime(String.valueOf(DateUtils.getCurrentTimeStamp()));
            agencyVerify.setIsDeleted(0);
            agencyVerify.setSalaryVerifiedInAgencyCode("0");
            agencyVerify.setSalaryInfoVerifiedCode(null);
            agencyVerify.setPersonInfoVerifiedCode("0");
            agencyVerify.setAgencyInfoVerifiedCode("0");
            agencyVerify.setIsSubmitInAgency(0);
            agencyVerify.setIsSalarySubmit(0);
            agencyVerify.setIsPersonSubmit(0);
            agencyVerify.setIsAgencySubmit(0);
            agencyVerify.setIsConfirmSubmit(0);
            agencyVerify.setAuditExplain(null);
            agencyVerify.setRemark(null);
            agencyVerify.setIsSalaryChange(0);
            agencyVerify.setAddPersonNum(0);
            agencyVerify.setAddQuitPersonNum(0);
            agencyVerify.setDeletePersonNum(0);
            agencyVerify.setIsThirteen(0);
            agencyVerify.setIsPayDataCreated(0);
            agencyVerify.setIsBankDataCreated(0);
            agencyVerify.setYear(year);
            agencyVerify.setIsAuto("0");
            agencyVerify.setIsVerifyEnd(null);
            agencyVerify.setIsPaymentAgency(1);
            agencyVerify.setIsMonthEnd(0);
            agencyVerify.setMofDivCode(userDTO.getProvince());
            addList.add(agencyVerify);
        }


        /**
         * 将addList 存入 AgencyInfo,AgencyVerify,AgencyExt表中
         */
       if (addList.size()>0){
        iAgencyVerifyDao.insertAgencyInfo(addList);
        iAgencyVerifyDao.insertAgencyExt(addList);
           // is_leaf =0 的时候不往这里插入
          for(AgencyVerify agencyVerify:addList){
              if(!"0".equals(agencyVerify.getIsLeaf())){
                  agencyVerifyAdd.add(agencyVerify);

              }
          }
          if(agencyVerifyAdd.size()>0){
              // is_leaf =0 的时候不往这里插入
              iAgencyVerifyDao.insertAgencyVerify(agencyVerifyAdd);
             }
            }
        if(updateList.size()>0){
             iAgencyInfoDao.updateAgencyInfoCodeParentId(updateList);
             iAgencyVerifyDao.updateAgencyVerifyCode(updateList);
             iPersonExtDao.updatePersonExtDaoCode(updateList);
             iPersonOperateDao.updatePersonOperateCode(updateList);
             iPersonExtSubmitDao.updatePersonExtSubmitCode(updateList);
             iPersonExtBeginDao.updatePersonExtBeginCode(updateList);
        }
       return agencyInfoList;
    }

    @Override
    public List<Map<String, Object>> selectPersonTransfer(String province, String month) {
        return iAgencyVerifyDao.selectPersonTransfer(province,month);
    }

    @Override
    public String currentMonth(String province) {
        return iAgencyVerifyDao.currentMonth(province);
    }
    @Override
    public String currentYear(String province) {
        return iAgencyVerifyDao.currentYear(province);
    }
    @Override
    public List<AgencyVerify> queryAgencyVerify(List<AgencyVerify> agencyVerifies) {
        return iAgencyVerifyDao.queryAgencyVerify(agencyVerifies);
    }

    @Override
    public PageDTO<AgencyVerify> queryAgencyVerifyData(PaginationDTO paginationDTO, Map<String, Object> params, String... column) {
        int total=iAgencyVerifyDao.queryAgencyVerifyCount(params);
        List<AgencyVerify> data=iAgencyVerifyDao.queryAgencyVerifyData(paginationDTO,params,column);
        PageDTO<AgencyVerify> pageDTO = new PageDTO<>();
        pageDTO.setRows(data);
        pageDTO.setTotal(total);
        return pageDTO;
    }
}
